<template>
  <el-container>
    <el-aside width="300px" v-loading="menuLoading">
      <el-container>
        <el-header>
          <el-input placeholder="输入关键字进行过滤" v-model="menuFilterText" clearable></el-input>
        </el-header>
        <el-main class="no-padding">
          <el-tree
            ref="menuTreeRef"
            class="menu"
            node-key="id"
            :data="menuList"
            :props="menuProps"
            highlight-current
            check-strictly
            show-checkbox
            :expand-on-click-node="false"
            :filter-node-method="menuFilterNode"
            @node-click="menuClick"
          >
            <template #default="{ node, data }">
              <span class="custom-tree-node">
                <span class="label">{{ node.label }}</span>
                <span class="do">
                  <el-button icon="el-icon-plus" size="small" @click.stop="onEdit(node, data)"></el-button>
                </span>
              </span>
            </template>
          </el-tree>
        </el-main>
        <el-footer class="menu-footer">
          <el-button type="primary" size="small" icon="el-icon-plus" @click="onEdit()"></el-button>
          <el-button type="danger" size="small" plain icon="el-icon-delete" @click="onDelete()"></el-button>
        </el-footer>
      </el-container>
    </el-aside>
    <el-container>
      <el-main class="no-padding" style="padding: 20px" ref="mainRef">
        <menu-form ref="menuFormRef" :menu-list="menuList"></menu-form>
      </el-main>
    </el-container>
  </el-container>
</template>

<script setup lang="ts">
import { ref, watch, onMounted } from 'vue'
import MenuForm from './form.vue'
import type { IMenu } from '@/api/menu/type'
import { ElTree, ElMain, ElMessage, ElMessageBox } from 'element-plus'
import { MenuApi } from '@/api/menu'

const menuLoading = ref<boolean>(false)
const menuFilterText = ref<string>('')
const menuList = ref<IMenu.MenuForm[]>([])
const menuProps = { label: (node: any) => node.meta.title }
const menuTreeRef = ref<InstanceType<typeof ElTree> | null>(null)
const menuFormRef = ref<InstanceType<typeof MenuForm> | null>(null)
const mainRef = ref<InstanceType<typeof ElMain> | null>(null)

onMounted(() => getMenuList())
watch(
  () => menuFilterText.value,
  () => menuTreeRef.value?.filter(menuFilterText.value)
)

//加载树数据
const getMenuList = async () => {
  try {
    menuLoading.value = true
    menuList.value = await MenuApi.list()
  } finally {
    menuLoading.value = false
  }
}

// 创建或者编辑菜单
const onEdit = async (node?: any, data?: any) => {
  let menuParams: IMenu.MenuForm = {
    id: 0,
    pid: data ? data.id : 0,
    path: '',
    name: '',
    component: '',
    redirect: '',
    meta: {
      type: 'menu',
      icon: '',
      title: '未命名' + new Date().getTime(),
      isHidden: false,
      isKeepAlive: true,
      sort: 1000,
      tag: ''
    }
  }

  try {
    menuLoading.value = true
    const response = await MenuApi.edit(menuParams)
    menuParams.id = response.id
    menuTreeRef.value?.append(menuParams, data ? node : null)
    menuTreeRef.value?.setCurrentKey(menuParams.id)
    menuFormRef.value?.setData(menuParams)
  } finally {
    menuLoading.value = false
  }
}

// 删除菜单
const onDelete = async () => {
  let CheckedNodes = menuTreeRef.value?.getCheckedNodes()
  if (CheckedNodes == undefined || CheckedNodes.length == 0) {
    ElMessage.warning('请选择需要删除的项')
    return false
  }

  const confirmResult = await ElMessageBox.confirm('确认删除已选择的菜单吗？', '提示', {
    type: 'warning',
    confirmButtonText: '删除',
    confirmButtonClass: 'el-button--danger'
  }).catch(() => {})
  if (confirmResult != 'confirm') return false

  try {
    menuLoading.value = true
    await MenuApi.delete({ ids: CheckedNodes.map((item) => item.id) })
    CheckedNodes.forEach((item) => {
      let node = menuTreeRef.value?.getNode(item)
      if (node != undefined && node.isCurrent) {
        menuFormRef.value?.setData({} as IMenu.MenuForm)
      }
      menuTreeRef.value?.remove(item)
    })
    ElMessage.success('菜单删除成功')
  } finally {
    menuLoading.value = false
  }
}

//树点击
const menuClick = (data: { [key: string]: any }) => {
  menuFormRef.value?.setData(data as IMenu.MenuForm)
  if (mainRef.value) mainRef.value!.$el.scrollTop = 0
}

//树过滤
const menuFilterNode = (value: string, data: { [key: string]: any }) => {
  if (!value) return true
  let targetText = data.meta.title
  return targetText.indexOf(value) !== -1
}
</script>

<style scoped>
.menu:deep(.el-tree-node__label) {
  display: flex;
  flex: 1;
  height: 100%;
}
.menu-footer {
  display: flex;
  height: 50px;
  justify-content: space-between;
  button {
    width: 48px;
    font-size: 11px;
  }
}
.custom-tree-node {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  height: 100%;
  padding-right: 24px;
}
.custom-tree-node .label {
  display: flex;
  align-items: center;
  height: 100%;
}
.custom-tree-node .label .el-tag {
  margin-left: 5px;
}
.custom-tree-node .do {
  display: none;
}
.custom-tree-node .do i {
  margin-left: 5px;
  color: #999;
}
.custom-tree-node .do i:hover {
  color: #333;
}

.custom-tree-node:hover .do {
  display: inline-block;
}
</style>
